Haskell 中的 map, filter, fold 教程

1. 简介

在函数式编程中,map, filter, 和 fold 是三个非常强大的高阶函数,它们允许你以一种简洁和声明式的方式处理列表(或其他可遍历的数据结构)。本教程将详细介绍这三个函数,并通过代码示例和实践练习帮助你掌握它们的使用。

2. map 函数

2.1 理论解释

map 函数接受一个函数和一个列表,并将该函数应用到列表的每个元素上,返回一个新的列表。换句话说,map 将一个函数“映射”到一个列表的所有元素上。

2.2 代码示例

-- 定义一个简单的函数,将数字加倍
double :: Int -> Int
double x = x * 2

-- 使用 map 将 double 函数应用到列表 [1, 2, 3, 4] 上
result :: [Int]
result = map double [1, 2, 3, 4]

-- 输出结果
main :: IO ()
main = print result  -- 输出: [2, 4, 6, 8]

2.3 实践练习

编写一个函数 square,它接受一个整数并返回其平方。然后使用 map 将 square 函数应用到一个包含前 10 个自然数的列表上。

3. filter 函数

3.1 理论解释

filter 函数接受一个谓词(即返回布尔值的函数)和一个列表,并返回一个新列表,其中只包含使谓词返回 True 的元素。

3.2 代码示例

-- 定义一个谓词函数,判断数字是否为偶数
isEven :: Int -> Bool
isEven x = x `mod` 2 == 0

-- 使用 filter 过滤出列表 [1, 2, 3, 4, 5] 中的偶数
result :: [Int]
result = filter isEven [1, 2, 3, 4, 5]

-- 输出结果
main :: IO ()
main = print result  -- 输出: [2, 4]

3.3 实践练习

编写一个谓词函数 isPositive,它接受一个整数并返回 True 如果该整数为正数。然后使用 filter 过滤出一个包含负数和正数的列表,只保留正数。

4. fold 函数

4.1 理论解释

fold 函数(也称为 reduce)接受一个二元函数、一个初始值和一个列表,并从左到右或从右到左将二元函数应用到列表的元素和累积值上,最终返回一个单一的值。

Haskell 中有两个主要的 fold 函数:foldl 和 foldr。foldl 从左到右折叠,而 foldr 从右到左折叠。

4.2 代码示例

-- 使用 foldl 计算列表 [1, 2, 3, 4] 的和
sumList :: [Int] -> Int
sumList = foldl (+) 0

-- 使用 foldr 计算列表 [1, 2, 3, 4] 的乘积
productList :: [Int] -> Int
productList = foldr (*) 1

-- 输出结果
main :: IO ()
main = do
    print (sumList [1, 2, 3, 4])  -- 输出: 10
    print (productList [1, 2, 3, 4])  -- 输出: 24

4.3 实践练习

编写一个函数 concatStrings,它使用 foldr 将一个字符串列表连接成一个单一的字符串。例如,concatStrings ["Hello", " ", "World"] 应该返回 "Hello World"。

5. 综合练习

结合 map, filter, 和 fold 函数,编写一个程序,计算一个整数列表中所有正数的平方和。

-- 定义一个函数,计算正数的平方和
sumOfSquaresOfPositives :: [Int] -> Int
sumOfSquaresOfPositives = foldl (+) 0 . map (^2) . filter (>0)

-- 输出结果
main :: IO ()
main = print (sumOfSquaresOfPositives [1, -2, 3, -4, 5])  -- 输出: 35

6. 总结

通过本教程,你应该已经掌握了 map, filter, 和 fold 这三个强大的函数。它们是函数式编程中的基本工具,能够帮助你以一种简洁和优雅的方式处理数据。继续练习和探索这些函数,你将能够在 Haskell 中编写出更加复杂和高效的程序。

7. 下一步

接下来,你可以继续学习 Haskell 中的其他高阶函数,如 zip, zipWith, scanl, scanr 等。此外,你还可以深入了解 Haskell 的类型系统和类型类,这些知识将帮助你更好地理解和使用这些函数。